home *** CD-ROM | disk | FTP | other *** search
/ IRIX 6.5 Applications 2004 April / SGI IRIX 6.5 Applications 2004 April.iso / dist / mozilla.idb / var / netscape / mozilla / chrome / toolkit.jar.z / toolkit.jar / content / global / config.js < prev    next >
Text File  |  2003-11-11  |  16KB  |  511 lines

  1. /* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
  2.  * The contents of this file are subject to the Netscape Public
  3.  * License Version 1.1 (the "License"); you may not use this file
  4.  * except in compliance with the License. You may obtain a copy of
  5.  * the License at http://www.mozilla.org/NPL/
  6.  * 
  7.  * Software distributed under the License is distributed on an "AS
  8.  * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
  9.  * implied. See the License for the specific language governing
  10.  * rights and limitations under the License.
  11.  * 
  12.  * The Original Code is Mozilla Communicator client code, released
  13.  * March 31, 1998.
  14.  * 
  15.  * The Initial Developer of the Original Code is Netscape
  16.  * Communications Corporation. Portions created by Netscape are
  17.  * Copyright (C) 1998-1999 Netscape Communications Corporation. All
  18.  * Rights Reserved.
  19.  *
  20.  * Contributors:
  21.  *  Chip Clark <chipc@netscape.com>
  22.  *  Seth Spitzer <sspitzer@netscape.com>
  23.  *  Neil Rashbrook <neil@parkwaycc.co.uk>
  24.  */
  25.  
  26. const nsIPrefLocalizedString = Components.interfaces.nsIPrefLocalizedString;
  27. const nsISupportsString = Components.interfaces.nsISupportsString;
  28. const nsIPromptService = Components.interfaces.nsIPromptService;
  29. const nsIPrefService = Components.interfaces.nsIPrefService;
  30. const nsIPrefBranch = Components.interfaces.nsIPrefBranch;
  31. const nsIClipboardHelper = Components.interfaces.nsIClipboardHelper;
  32. const nsIAtomService = Components.interfaces.nsIAtomService;
  33.  
  34. const nsSupportsString_CONTRACTID = "@mozilla.org/supports-string;1";
  35. const nsPrompt_CONTRACTID = "@mozilla.org/embedcomp/prompt-service;1";
  36. const nsPrefService_CONTRACTID = "@mozilla.org/preferences-service;1";
  37. const nsClipboardHelper_CONTRACTID = "@mozilla.org/widget/clipboardhelper;1";
  38. const nsAtomService_CONTRACTID = "@mozilla.org/atom-service;1";
  39.  
  40. const gPromptService = Components.classes[nsPrompt_CONTRACTID].getService(nsIPromptService);
  41. const gPrefService = Components.classes[nsPrefService_CONTRACTID].getService(nsIPrefService);
  42. const gPrefBranch = gPrefService.getBranch(null).QueryInterface(Components.interfaces.nsIPrefBranchInternal);
  43. const gClipboardHelper = Components.classes[nsClipboardHelper_CONTRACTID].getService(nsIClipboardHelper);
  44. const gAtomService = Components.classes[nsAtomService_CONTRACTID].getService(nsIAtomService);
  45.  
  46. var gLockAtoms = [gAtomService.getAtom("default"), gAtomService.getAtom("user"), gAtomService.getAtom("locked")];
  47. // we get these from a string bundle
  48. var gLockStrs = [];
  49. var gTypeStrs = [];
  50.  
  51. const PREF_IS_DEFAULT_VALUE = 0;
  52. const PREF_IS_USER_SET = 1;
  53. const PREF_IS_LOCKED = 2;
  54.  
  55. var gPrefHash = {};
  56. var gPrefArray = [];
  57. var gPrefView = gPrefArray; // share the JS array
  58. var gFastIndex = 0;
  59. var gSortedColumn = "prefCol";
  60. var gSortFunction = null;
  61. var gSortDirection = 1; // 1 is ascending; -1 is descending
  62. var gConfigBundle = null;
  63.  
  64. var view = {
  65.   get rowCount() { return gPrefView.length; },
  66.   getCellText : function(index, col) {
  67.     if (!(index in gPrefView))
  68.       return "";
  69.     
  70.     var value = gPrefView[index][col];
  71.  
  72.     switch (col) {
  73.       case "lockCol":           
  74.         return gLockStrs[value];
  75.       case "typeCol":
  76.         return gTypeStrs[value];
  77.       default:
  78.         return value;
  79.     }
  80.   },
  81.   getRowProperties : function(index, prop) {},
  82.   getCellProperties : function(index, col, prop) {
  83.     if (index in gPrefView)
  84.       prop.AppendElement(gLockAtoms[gPrefView[index].lockCol]);
  85.   },
  86.   getColumnProperties : function(col, elt, prop) {},
  87.   treebox : null,
  88.   selection : null,
  89.   isContainer : function(index) { return false; },
  90.   isContainerOpen : function(index) { return false; },
  91.   isContainerEmpty : function(index) { return false; },
  92.   isSorted : function() { return true; },
  93.   canDropOn : function(index) { return false; },
  94.   canDropBeforeAfter : function(index, before) { return false; },
  95.   drop : function(row,orientation) {},
  96.   setTree : function(out) { this.treebox = out; },
  97.   getParentIndex: function(rowIndex) { return -1; },
  98.   hasNextSibling: function(rowIndex, afterIndex) { return false; },
  99.   getLevel: function(index) { return 1; },
  100.   getImageSrc: function(row, colID) { return ""; },
  101.   toggleOpenState : function(index) {},
  102.   cycleHeader: function(colID, elt) {
  103.     var index = this.selection.currentIndex;
  104.     if (colID == gSortedColumn)
  105.       gSortDirection = -gSortDirection;
  106.     if (colID == gSortedColumn && gFastIndex == gPrefArray.length) {
  107.       gPrefArray.reverse();
  108.       if (gPrefView != gPrefArray)
  109.         gPrefView.reverse();
  110.       if (index >= 0)
  111.         index = gPrefView.length - index - 1;
  112.     }
  113.     else {
  114.       var pref = null;
  115.       if (index >= 0) {
  116.         if (gPrefArray != gPrefView)
  117.           index = gPrefView.length - index - 1;
  118.         else
  119.           pref = gPrefArray[index];
  120.       }
  121.       var old = document.getElementById(gSortedColumn);
  122.       old.setAttribute("sortDirection", "");
  123.       gPrefArray.sort(gSortFunction = gSortFunctions[colID]);
  124.       if (gPrefView != gPrefArray) {
  125.         if (colID == gSortedColumn)
  126.           gPrefView.reverse();
  127.         else
  128.           gPrefView.sort(gSortFunction);
  129.       }
  130.       gSortedColumn = colID;
  131.       if (pref)
  132.         index = getIndexOfPref(pref);
  133.     }
  134.     elt.setAttribute("sortDirection", gSortDirection > 0 ? "ascending" : "descending");
  135.     this.treebox.invalidate();
  136.     if (index >= 0) {
  137.       this.selection.select(index);
  138.       this.treebox.ensureRowIsVisible(index);
  139.     }
  140.     gFastIndex = gPrefArray.length;
  141.   },
  142.   selectionChanged : function() {},
  143.   cycleCell: function(row, colID) {},
  144.   isEditable: function(row, colID) {return false; },
  145.   setCellText: function(row, colID, value) {},
  146.   performAction: function(action) {},
  147.   performActionOnRow: function(action, row) {},
  148.   performActionOnCell: function(action, row, colID) {},
  149.   isSeparator: function(index) {return false; }
  150. };
  151.  
  152. // find the index in gPrefView of a pref object
  153. // or -1 if it does not exist in the filtered view
  154. function getViewIndexOfPref(pref)
  155. {
  156.   var low = -1, high = gPrefView.length;
  157.   var index = (low + high) >> 1;
  158.   while (index > low) {
  159.     var mid = gPrefView[index];
  160.     if (mid == pref)
  161.       return index;
  162.     if (gSortFunction(mid, pref) < 0)
  163.       low = index;
  164.     else
  165.       high = index;
  166.     index = (low + high) >> 1;
  167.   }
  168.   return -1;
  169. }
  170.  
  171. // find the index in gPrefArray of a pref object
  172. // either one that was looked up in gPrefHash
  173. // or in case it was moved after sorting
  174. function getIndexOfPref(pref)
  175. {
  176.   var low = -1, high = gFastIndex;
  177.   var index = (low + high) >> 1;
  178.   while (index > low) {
  179.     var mid = gPrefArray[index];
  180.     if (mid == pref)
  181.       return index;
  182.     if (gSortFunction(mid, pref) < 0)
  183.       low = index;
  184.     else
  185.       high = index;
  186.     index = (low + high) >> 1;
  187.   }
  188.  
  189.   for (index = gFastIndex; index < gPrefArray.length; ++index)
  190.     if (gPrefArray[index] == pref)
  191.       break;
  192.   return index;
  193. }
  194.  
  195. function getNearestIndexOfPref(pref)
  196. {
  197.   var low = -1, high = gFastIndex;
  198.   var index = (low + high) >> 1;
  199.   while (index > low) {
  200.     if (gSortFunction(gPrefArray[index], pref) < 0)
  201.       low = index;
  202.     else
  203.       high = index;
  204.     index = (low + high) >> 1;
  205.   }
  206.   return high;
  207. }
  208.  
  209. var gPrefListener =
  210. {
  211.   observe: function(subject, topic, prefName)
  212.   {
  213.     if (topic != "nsPref:changed")
  214.       return;
  215.  
  216.     if (/^capability\./.test(prefName)) // avoid displaying "private" preferences
  217.       return;
  218.  
  219.     var index = gPrefArray.length;
  220.     if (prefName in gPrefHash) {
  221.       index = getViewIndexOfPref(gPrefHash[prefName]);
  222.       fetchPref(prefName, getIndexOfPref(gPrefHash[prefName]));
  223.       if (index >= 0) {
  224.         // Might need to update the filtered view
  225.         gPrefView[index] = gPrefHash[prefName];
  226.         view.treebox.invalidateRow(index);
  227.       }
  228.       if (gSortedColumn == "lockCol" || gSortedColumn == "valueCol")
  229.         gFastIndex = 1; // TODO: reinsert and invalidate range
  230.     } else {
  231.       fetchPref(prefName, index);
  232.       if (index == gFastIndex) {
  233.         // Keep the array sorted by reinserting the pref object
  234.         var pref = gPrefArray.pop();
  235.         index = getNearestIndexOfPref(pref);
  236.         gPrefArray.splice(index, 0, pref);
  237.         gFastIndex = gPrefArray.length;
  238.       }
  239.       if (gPrefView == gPrefArray)
  240.         view.treebox.rowCountChanged(index, 1);
  241.     }
  242.   }
  243. };
  244.  
  245. function prefObject(prefName, prefIndex)
  246. {
  247.   this.prefCol = prefName;
  248. }
  249.  
  250. prefObject.prototype =
  251. {
  252.   lockCol: PREF_IS_DEFAULT_VALUE,
  253.   typeCol: nsIPrefBranch.PREF_STRING,
  254.   valueCol: ""
  255. };
  256.  
  257. function fetchPref(prefName, prefIndex)
  258. {
  259.   var pref = new prefObject(prefName);
  260.  
  261.   gPrefHash[prefName] = pref;
  262.   gPrefArray[prefIndex] = pref;
  263.  
  264.   if (gPrefBranch.prefIsLocked(prefName))
  265.     pref.lockCol = PREF_IS_LOCKED;
  266.   else if (gPrefBranch.prefHasUserValue(prefName))
  267.     pref.lockCol = PREF_IS_USER_SET;
  268.  
  269.   try {
  270.     switch (gPrefBranch.getPrefType(prefName)) {
  271.       case gPrefBranch.PREF_BOOL:
  272.         pref.typeCol = gPrefBranch.PREF_BOOL;
  273.         // convert to a string
  274.         pref.valueCol = gPrefBranch.getBoolPref(prefName).toString();
  275.         break;
  276.       case gPrefBranch.PREF_INT:
  277.         pref.typeCol = gPrefBranch.PREF_INT;
  278.         // convert to a string
  279.         pref.valueCol = gPrefBranch.getIntPref(prefName).toString();
  280.         break;
  281.       default:
  282.       case gPrefBranch.PREF_STRING:
  283.         pref.valueCol = gPrefBranch.getComplexValue(prefName, nsISupportsString).data;
  284.         // Try in case it's a localized string (will throw an exception if not)
  285.         if (pref.lockCol == PREF_IS_DEFAULT_VALUE)
  286.           pref.valueCol = gPrefBranch.getComplexValue(prefName, nsIPrefLocalizedString).data;
  287.         break;
  288.     }
  289.   } catch (e) {
  290.     // Also catch obscure cases in which you can't tell in advance
  291.     // that the pref exists but has no user or default value...
  292.   }
  293. }
  294.  
  295. function onConfigLoad()
  296. {
  297.   // Load strings
  298.   gConfigBundle = document.getElementById("configBundle");
  299.   document.title = gConfigBundle.getString("title");
  300.  
  301.   gLockStrs[PREF_IS_DEFAULT_VALUE] = gConfigBundle.getString("default");
  302.   gLockStrs[PREF_IS_USER_SET] = gConfigBundle.getString("user");
  303.   gLockStrs[PREF_IS_LOCKED] = gConfigBundle.getString("locked");
  304.  
  305.   gTypeStrs[nsIPrefBranch.PREF_STRING] = gConfigBundle.getString("string");
  306.   gTypeStrs[nsIPrefBranch.PREF_INT] = gConfigBundle.getString("int");
  307.   gTypeStrs[nsIPrefBranch.PREF_BOOL] = gConfigBundle.getString("bool");
  308.  
  309.   var prefCount = { value: 0 };
  310.   var prefArray = gPrefBranch.getChildList("", prefCount);
  311.  
  312.   for (var i = 0; i < prefCount.value; ++i) 
  313.   {
  314.     var prefName = prefArray[i];
  315.     if (/^capability\./.test(prefName)) // avoid displaying "private" preferences
  316.       continue;
  317.  
  318.     fetchPref(prefName, gPrefArray.length);
  319.   }
  320.  
  321.   var descending = document.getElementsByAttribute("sortDirection", "descending");
  322.   if (descending.length) {
  323.     gSortedColumn = descending[0].id;
  324.     gSortDirection = -1;
  325.   }
  326.   else {
  327.     var ascending = document.getElementsByAttribute("sortDirection", "ascending");
  328.     if (ascending.length)
  329.       gSortedColumn = ascending[0].id;
  330.     else
  331.       document.getElementById(gSortedColumn).setAttribute("sortDirection", "ascending");
  332.   }
  333.   gSortFunction = gSortFunctions[gSortedColumn];
  334.   gPrefArray.sort(gSortFunction);
  335.   gFastIndex = gPrefArray.length;
  336.   
  337.   gPrefBranch.addObserver("", gPrefListener, false);
  338.  
  339.   document.getElementById("configTree").view = view;
  340. }
  341.  
  342. function onConfigUnload()
  343. {
  344.   gPrefBranch.removeObserver("", gPrefListener);
  345.   document.getElementById("configTree").view = null;
  346. }
  347.  
  348. function FilterPrefs()
  349. {
  350.   var substring = document.getElementById("textbox").value.toString();
  351.   var prefCol = view.selection.currentIndex < 0 ? null : gPrefView[view.selection.currentIndex].prefCol;
  352.   var array = gPrefView;
  353.   gPrefView = gPrefArray;
  354.   if (substring) {
  355.     gPrefView = [];
  356.     for (var i = 0; i < gPrefArray.length; ++i)
  357.       if (gPrefArray[i].prefCol.toLowerCase().indexOf(substring) >= 0)
  358.         gPrefView.push(gPrefArray[i]);
  359.     if (gFastIndex < gPrefArray.length)
  360.       gPrefView.sort(gSortFunction);
  361.   }
  362.   view.treebox.invalidate();
  363.   view.treebox.rowCountChanged(array.length, gPrefView.length - array.length);
  364.   gotoPref(prefCol);
  365.   document.getElementById("button").disabled = !substring;
  366. }
  367.  
  368. function ClearFilter(button)
  369. {
  370.   var textbox = document.getElementById("textbox");
  371.   textbox.value = "";
  372.   textbox.focus();
  373.   FilterPrefs();
  374. }
  375.  
  376. function prefColSortFunction(x, y)
  377. {
  378.   if (x.prefCol > y.prefCol)
  379.     return gSortDirection;
  380.   if (x.prefCol < y.prefCol) 
  381.     return -gSortDirection;
  382.   return 0;
  383. }
  384.  
  385. function lockColSortFunction(x, y)
  386. {
  387.   if (x.lockCol != y.lockCol)
  388.     return gSortDirection * (y.lockCol - x.lockCol);
  389.   return prefColSortFunction(x, y);
  390. }
  391.  
  392. function typeColSortFunction(x, y)
  393. {
  394.   if (x.typeCol != y.typeCol) 
  395.     return gSortDirection * (y.typeCol - x.typeCol);
  396.   return prefColSortFunction(x, y);
  397. }
  398.  
  399. function valueColSortFunction(x, y)
  400. {
  401.   if (x.valueCol > y.valueCol)
  402.     return gSortDirection;
  403.   if (x.valueCol < y.valueCol) 
  404.     return -gSortDirection;
  405.   return prefColSortFunction(x, y);
  406. }
  407.  
  408. const gSortFunctions =
  409. {
  410.   prefCol: prefColSortFunction, 
  411.   lockCol: lockColSortFunction, 
  412.   typeCol: typeColSortFunction, 
  413.   valueCol: valueColSortFunction
  414. };
  415.  
  416. function updateContextMenu(popup) {
  417.   if (view.selection.currentIndex < 0)
  418.     return false;
  419.   var pref = gPrefView[view.selection.currentIndex];
  420.   var reset = popup.lastChild;
  421.   reset.setAttribute("disabled", pref.lockCol != PREF_IS_USER_SET);
  422.   var modify = reset.previousSibling;
  423.   modify.setAttribute("disabled", pref.lockCol == PREF_IS_LOCKED);
  424.   return true;
  425. }
  426.  
  427. function copyName()
  428. {
  429.   gClipboardHelper.copyString(gPrefView[view.selection.currentIndex].prefCol);
  430. }
  431.  
  432. function copyValue()
  433. {
  434.   gClipboardHelper.copyString(gPrefView[view.selection.currentIndex].valueCol);
  435. }
  436.  
  437. function ModifySelected()
  438. {
  439.   ModifyPref(gPrefView[view.selection.currentIndex]);
  440. }
  441.  
  442. function ResetSelected()
  443. {
  444.   var entry = gPrefView[view.selection.currentIndex];
  445.   gPrefBranch.clearUserPref(entry.prefCol);
  446. }
  447.  
  448. function NewPref(type)
  449. {
  450.   var result = { value: "" };
  451.   var dummy = { value: 0 };
  452.   // XXX get these from a string bundle
  453.   if (gPromptService.prompt(window,
  454.                             gConfigBundle.getFormattedString("new_title", [gTypeStrs[type]]),
  455.                             gConfigBundle.getString("new_prompt"),
  456.                             result,
  457.                             null,
  458.                             dummy)) {
  459.     var pref;
  460.     if (result.value in gPrefHash)
  461.       pref = gPrefHash[result.value];
  462.     else
  463.       pref = { prefCol: result.value, lockCol: PREF_IS_DEFAULT_VALUE, typeCol: type, valueCol: "" };
  464.     if (ModifyPref(pref))
  465.       setTimeout(gotoPref, 0, result.value);
  466.   }
  467. }
  468.  
  469. function gotoPref(pref) {
  470.   // make sure the pref exists and is displayed in the current view
  471.   var index = pref in gPrefHash ? getViewIndexOfPref(gPrefHash[pref]) : -1;
  472.   if (index >= 0) {
  473.     view.selection.select(index);
  474.     view.treebox.ensureRowIsVisible(index);
  475.   } else {
  476.     view.selection.clearSelection();
  477.     view.selection.currentIndex = -1;
  478.   }
  479. }
  480.  
  481. function ModifyPref(entry)
  482. {
  483.   if (entry.lockCol == PREF_IS_LOCKED)
  484.     return false;
  485.   var result = { value: entry.valueCol };
  486.   var dummy = { value: 0 };
  487.   // XXX get this from a string bundle
  488.   if (!gPromptService.prompt(window,
  489.                              gConfigBundle.getFormattedString("modify_title", [gTypeStrs[entry.typeCol]]),
  490.                              entry.prefCol,
  491.                              result,
  492.                              null,
  493.                              dummy))
  494.     return false;
  495.   switch (entry.typeCol) {
  496.     case nsIPrefBranch.PREF_BOOL:
  497.       gPrefBranch.setBoolPref(entry.prefCol, eval(result.value));
  498.       break;
  499.     case nsIPrefBranch.PREF_INT:
  500.       gPrefBranch.setIntPref(entry.prefCol, eval(result.value));
  501.       break;
  502.     default:
  503.     case nsIPrefBranch.PREF_STRING:
  504.       var supportsString = Components.classes[nsSupportsString_CONTRACTID].createInstance(nsISupportsString);
  505.       supportsString.data = result.value;
  506.       gPrefBranch.setComplexValue(entry.prefCol, nsISupportsString, supportsString);
  507.       break;
  508.   }
  509.   return true;
  510. }
  511.